package org.totoro.memory.jmm;

/**
 * 什么是happens-before关系？ 这个关系其实就是一个保证而已，那么保证什么呢？它保证一条语句对内存的写操作对另一条语句是可见的。换句话说，如果写操作A和读操作B存在happens-before这种关系，那么写操作在结束以后都操作才能开始。
 * <p>
 * 下面是Java内存模型中的八条可保证happen—before的规则，它们无需任何同步器协助就已经存在，可以在编码中直接使用。
 * 1、程序次序规则：在一个单独的线程中，按照程序代码的执行流顺序，（时间上）先执行的操作happen—before（时间上）后执行的操作。
 * 2、管理锁定规则：一个unlock操作happen—before后面（时间上的先后顺序，下同）对同一个锁的lock操作。
 * 3、volatile变量规则：对一个volatile变量的写操作happen—before后面对该变量的读操作。
 * 4、线程启动规则：Thread对象的start（）方法happen—before此线程的每一个动作。
 * 5、线程终止规则：线程的所有操作都happen—before对此线程的终止检测，可以通过Thread.join（）方法结束、Thread.isAlive（）的返回值等手段检测到线程已经终止执行。
 * 6、线程中断规则：对线程interrupt（）方法的调用happen—before发生于被中断线程的代码检测到中断时事件的发生。
 * 7、对象终结规则：一个对象的初始化完成（构造函数执行结束）happen—before它的finalize（）方法的开始。
 * 8、传递性：如果操作A happen—before操作B，操作B happen—before操作C，那么可以得出A happen—before操作C。
 * <p>
 * 这里的八个规则除了第三个以外都容易理解。所以专门讲一下volatile变量规则。
 * <p>
 * 1、 对volatile变量执行写操作时，会在写操作后加入一条store屏障指令
 * <p>
 * 2、 对volatile变量执行读操作时，会在读操作前加入一条load屏障指令。
 * <p>
 * 通俗得讲，volatile变量在每次被线程访问时，都强迫从主内存中读该变量的值，而当该变量发生变化时，又会强迫将最新的值刷新到主内存。这样任何时刻，不同的线程总是能够看到该变量的最新值。
 * <p>
 * 如果你不能够理解，我们可以采取一种极端的思维方式：如果有两个线程的话，对于一个普通变量，在java内存模型中它是有三个拷贝的，一个在主内存，另外两个在线程的工作内存里。如果刷新不及时，那么就可能导致两个工作内存中的变量值不一致。但是对于volatile变量，你完全可以假定其只有一份而且唯一一份拷贝在主内存中发生，所以当两个线程想对volatile变量进行更改或者读取的时候，总是得等其中一个线程完成以后才行。
 *
 * @author daocr
 * @date 2020/3/1
 */
public class JmmHappensBefore {


}
